from os.path import splitext

import pyglet
from pyglet import resource
from pyglet.gl import *

from pyglons import globals as g
from pyglons.state import State, IterStateManager, Stop, stop
from pyglons.states import _BaseState

import logging
log = logging.getLogger(__name__)


class SplashStepState(State):
    def __init__(self, parent=None, timeout=None):
        self.parent = parent
        self.timeout = timeout

    def on_enter(self):
        window = self.parent.window
        window.push_handlers(
            self.on_draw,
            self.on_key_press,
            self.on_resize,
        )
        if self.timeout:
            pyglet.clock.schedule_once(self.next, self.timeout)
        self.on_resize(window.width, window.height)

    def on_exit(self):
        self.parent.window.pop_handlers()
        pyglet.clock.unschedule(self.next)

    def next(self, *args):
        self.parent.pop_state()

    def on_key_press(self, symbol, modifiers):
        self.next()

    def on_update(self, dt):
        pass

    def on_resize(self, width, height):
        pass


class LabelSplashStepState(SplashStepState):
    def __init__(self, parent, label, timeout=2.0):
        SplashStepState.__init__(self, parent, timeout)
        self.label = label

    def on_draw(self):
        glClear(GL_COLOR_BUFFER_BIT)
        glLoadIdentity()

        self.label.draw()


class HTMLSplashStepState(LabelSplashStepState):
    def __init__(self, parent, html, timeout=2.0, **options):
        opts = dict(halign="center", valign="center")
        opts.update(options)
        label = pyglet.text.HTMLLabel(html, **opts)

        LabelSplashStepState.__init__(self, parent, label, timeout)

    def on_resize(self, width, height):
        self.label.x = width / 2
        self.label.y = height / 2


class ImageSplashStepState(SplashStepState):
    def __init__(self, parent, filename, timeout=2.0):
        SplashStepState.__init__(self, parent, timeout)
        self.image = resource.image(filename)

    def on_resize(self, width, height):
        self.img_x = (width / 2) - (self.image.width / 2)
        self.img_y = (height / 2) - (self.image.height / 2)

    def on_draw(self):
        glClear(GL_COLOR_BUFFER_BIT)
        glLoadIdentity()

        self.image.blit(self.img_x, self.img_y)


class VideoSplashStepState(SplashStepState):
    def __init__(self, parent, filename):
        SplashStepState.__init__(self, parent)
        self.video = resource.media(filename)
        self.player = player = pyglet.media.Player()
        player.queue(self.video)
        player.eos_action = self.player.EOS_PAUSE
        player.play()

    def on_enter(self):
        SplashStepState.on_enter(self)
        self.player.set_handler('on_eos', self.on_eos)

    def on_resize(self, width, height):
        vf = self.video.video_format
        self.vid_x = (width / 2) - (vf.width / 2)
        self.vid_y = (height / 2) - (vf.height / 2)

    def on_draw(self):
        glClear(GL_COLOR_BUFFER_BIT)
        glLoadIdentity()
        self.player.get_texture().blit(self.vid_x, self.vid_y)

    def on_eos(self):
        self.player.pause()
        del self.player
        del self.video
        self.video = None
        self.next()


class PyglonsSplashState(_BaseState, IterStateManager):
    """ takes an iterable of states and shows them one after the other 
    """
    def __init__(self, states=None):
        self._basestate.__init__(self)
        IterStateManager.__init__(self, states)

    def on_enter(self):
        self._basestate.on_enter(self)
        self.pop_state()
    
    def pop_state(self):
        try:
            IterStateManager.pop_state(self)
        except Stop:
            g.app.pop_state()

    def on_update(self, dt):
        self.state.on_update(dt)


class SimpleSplashState(PyglonsSplashState):
    """ works just like SplashState but you can pass a list of strings
    (mixed with real SplashStepState's if you want) and SimpleSplashState 
    guesses which SplashStepState to use. 
    """

    ext_map = {
        '.html': lambda owner, thing: HTMLSplashStepState(owner, 
                                        resource.text(thing).text),
        '.jpg': ImageSplashStepState,
        '.png': ImageSplashStepState,
        '.avi': VideoSplashStepState,
        '.mpg': VideoSplashStepState,
    } 

    def __init__(self, things):
        PyglonsSplashState.__init__(self, self.generator(things))

    def generator(self, things):
        for thing in things:
            ret = None
            if isinstance(thing, SplashStepState):
                ret = thing
            elif isinstance(thing, (str, unicode)):
                ext = splitext(thing)[1].lower()
                try:
                    ret = self.ext_map[ext](self, thing)
                except KeyError:
                    pass

            if ret:
                yield ret
            else:
                raise ValueError(thing)


class OLD__SplashState(_BaseState):
    """ Splash screen state, takes a list of images and/or videos 
    and displays them in order. Any step can be skipped by pessing
    a key """

    def __init__(self, images_and_videos):
        self._basestate.__init__(self)
        self.images_and_videos = images_and_videos
        self.image = None
        self.video = None

    def on_enter(self):
        self._basestate.on_enter(self)
        self.get_next_image()

    def on_exit(self):
        self._basestate.on_exit(self)
        pyglet.clock.unschedule(self.auto_next_image)

    def on_eos(self):
        self.player.pause()
        del self.player
        del self.video
        self.video = None
        self.get_next_image()

    def auto_next_image(self, dt):
        log.debug("timed out")
        self.get_next_image()

    def get_next_image(self, *nothing):
        try:
            thing = self.images_and_videos.pop()
        except IndexError:
            log.debug("no more images")
            g.app.pop_state()
            return

        self.video = None
        self.image = None

        ext = splitext(thing)[1].lower()
        if ext in ('.jpg', '.png', '.gif'):
            log.debug("loading image %s" % thing)
            self.image = resource.image(thing)
            pyglet.clock.schedule_once(self.auto_next_image, 5.0)
        else:
            log.debug("loading video %s" % thing)
            self.video = resource.media(thing)
            self.player = player = pyglet.media.Player()
            self.player.queue(self.video)
            self.player.eos_action = self.player.EOS_PAUSE
            self.player.set_handler('on_eos', self.on_eos)
            self.player.play()

        self.calc_pos()

    def calc_pos(self):
        image = self.image if self.image else self.video.video_format

        self.img_x = (self.window.width / 2) - (image.width / 2)
        self.img_y = (self.window.height / 2) - (image.height / 2)

    def on_resize(self, width, height):
        self._basestate.on_resize(self, width, height)
        if self.image or self.video:
            self.calc_pos()

    def on_draw(self):
        glClear(GL_COLOR_BUFFER_BIT)
        glLoadIdentity()
        if self.image:
            self.image.blit(self.img_x, self.img_y)
        else:
            self.player.get_texture().blit(self.img_x, self.img_y)

    def on_key_press(self, symbol, modifiers):
        if self._basestate.on_key_press(self, symbol, modifiers):
            return 
        if self.image:
            self.get_next_image()
        else:
            self.on_eos()


